package com.gscitysfy.cus.drain.aspects;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.gscitysfy.cloudfrmwk.portal.feign.DictionaryService;
import com.gscitysfy.cus.drain.annotations.DictTranslation;
import com.gscitysfy.cus.drain.annotations.FieldParam;
import com.gscitysfy.cus.drain.constants.RedisKeyConstant;
import com.gscitysfy.cus.drain.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 葛守跃
 * @version 1.0.0
 * @ClassName TranslateFieldAspect
 * @Description 字典翻译注解解析类
 * @creatTime 2022/10/13 10:06
 */
@Aspect
@Component
@Slf4j
public class TranslateFieldAspect {

    @Resource
    private DictionaryService dictionaryService;

    @Resource
    private RedisUtil redisUtil;

    /**
     * 翻译字典值
     *
     * @param joinPoint
     * @throws Throwable
     * @returnaho
     */
    @Around("@annotation(com.gscitysfy.cus.drain.annotations.DictTranslation)")
    public Object aroundMethodDict(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        if (Objects.isNull(result)) {
            return null;
        }
        //获取返回值类型
        Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
        //获取需要翻译的字段的字典值
        String returnJsonResult = JSONObject.toJSONString(result, SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteMapNullValue);
        //开始解析（翻译字段注解参数指定的字段）
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //获取注解上参数
        DictTranslation annotation = method.getAnnotation(DictTranslation.class);
        FieldParam[] fieldParams = annotation.value();
        //遍历
        for (FieldParam fieldParam : fieldParams) {
            log.debug("开始翻译字典CODE:{},取值字段：{},取值字段值类型：{}.",
                    fieldParam.dictType(), fieldParam.targetField(), fieldParam.targetFieldValueClazz());
            Pattern dictPattern = getPattern(fieldParam);
            Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
            StringBuffer sb = new StringBuffer();
            //转义字段
            this.translateDict(fieldParam, dictPattern, dictMatcher, sb);
            dictMatcher.appendTail(sb);
            returnJsonResult = sb.toString();
        }
        result = JSONObject.parseObject(returnJsonResult, returnType);
        return result;
    }

    /**
     * 字典值转义为中文
     *
     * @param fieldParam
     * @param fieldPattern
     * @param fieldMatcher
     * @param sb
     */
    private void translateDict(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) {
        //字典数据要缓存起来
        Map<String, String> dictNames = getDictMapByCode(fieldParam);
        while (fieldMatcher.find()) {
            //取出要翻译字段对应的值
            Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
            if (dictValueMatcher.find()) {
                String group = dictValueMatcher.group();
                //属性无值
                if (group.split(StrUtil.COLON).length <= 1) {
                    continue;
                }
                String dictName = StrUtil.EMPTY;
                //获取字典值
                String dictValue = group.split(StrUtil.COLON)[1].replace("\"", StrUtil.EMPTY);

                if (StringUtils.isNotBlank(dictValue) && !StrUtil.NULL.equalsIgnoreCase(dictValue)) {
                    //多值
                    String[] values = dictValue.split(StrUtil.COMMA);
                    if (values.length > 1) {
                        List<String> dicValues = new ArrayList<>();
                        for (String value : values) {
                            dicValues.add(dictNames.get(value));
                        }
                        dictName = StringUtils.join(dicValues, StrUtil.COMMA);
                    } else {
                        dictName = dictNames.get(dictValue);
                    }
                }
                String s = "\"" + fieldParam.targetField() + "Desc" + "\":\"" + dictName + "\"," + fieldMatcher.group();
                log.debug("拼接后字符串:{}", s);
                fieldMatcher.appendReplacement(sb, s);
            }
        }
    }

    /**
     * 获取对应的正则式
     *
     * @param fieldParam
     * @return
     */
    private Pattern getPattern(FieldParam fieldParam) {
        Pattern fieldPattern;//属性整型 字符型
        if (fieldParam.targetFieldValueClazz().equals(Integer.class)) {
            fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":(\\d+)?");
        } else {
            fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":\"([0-9a-zA-Z_,.-]+)?\"");
        }
        return fieldPattern;
    }

    /**
     * 去除键值中的空格
     *
     * @return
     */
    private Map<String, String> replaceSpace(Map<String, String> map) {
        Map<String, String> data = new HashMap<>(16);
        if (Objects.nonNull(map)) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                data.put(entry.getKey().replace(" ", ""), entry.getValue());
            }
        }
        return data;
    }

    /**
     * 根据code查询code-name/note-name
     *
     * @param fieldParam
     * @return
     */
    private Map<String, String> getDictMapByCode(FieldParam fieldParam) {
        Map<String, String> dictNames;
        String code = fieldParam.dictType();

        Map<Object, Object> dictMap = redisUtil.hmget(RedisKeyConstant.DATA_DICT_KEY + code);
        //缓存没有，则统一共工作台获取
        if (Objects.isNull(dictMap) || dictMap.isEmpty()) {
            if (!fieldParam.haveNote()) {
                dictNames = dictionaryService.getDictionaryMap(fieldParam.dictType()).getData();
            } else {
                dictNames = dictionaryService.getDictionaryNotes1AndNameMap(fieldParam.dictType()).getData();
            }
            dictMap = new HashMap<>(16);
            if (Objects.nonNull(dictNames)) {
                dictMap.putAll(dictNames);
            }
            redisUtil.hmset(RedisKeyConstant.DATA_DICT_KEY + fieldParam.dictType(), dictMap);
        } else {
            //取缓存值
            dictNames = new HashMap<>(16);
            for (Map.Entry<Object, Object> entry : dictMap.entrySet()) {
                dictNames.put(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        return this.replaceSpace(dictNames);
    }
}
